home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / UXTERM.C < prev    next >
C/C++ Source or Header  |  1992-05-05  |  17KB  |  643 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/uxterm.c,v 1.19 1992/05/05 06:38:52 jinx Exp $
  4.  
  5. Copyright (c) 1990-1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. #include "ux.h"
  36. #include "uxterm.h"
  37. #include "uxio.h"
  38. #include "ospty.h"
  39.  
  40. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  41.  
  42. #ifndef ISTRIP
  43. #define ISTRIP 0
  44. #endif
  45. #ifndef CS8
  46. #define CS8 0
  47. #endif
  48. #ifndef PARENB
  49. #define PARENB 0
  50. #endif
  51.  
  52. #else
  53. #ifdef HAVE_BSD_TTY_DRIVER
  54.  
  55. /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
  56. #ifndef LPASS8
  57. #define LPASS8 0
  58. #endif
  59.  
  60. #endif /* HAVE_BSD_TTY_DRIVER */
  61. #endif /* not HAVE_TERMIOS nor HAVE_TERMIO */
  62.  
  63. struct terminal_state
  64. {
  65.   int buffer;
  66.   Ttty_state state;
  67. };
  68.  
  69. static struct terminal_state * terminal_table;
  70. #define TERMINAL_BUFFER(channel) ((terminal_table[(channel)]) . buffer)
  71. #define TERMINAL_ORIGINAL_STATE(channel) ((terminal_table[(channel)]) . state)
  72.  
  73. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  74. #define TIO(s) (& ((s) -> tio))
  75. #endif
  76.  
  77. void
  78. DEFUN_VOID (UX_initialize_terminals)
  79. {
  80.   terminal_table =
  81.     (UX_malloc (OS_channel_table_size * (sizeof (struct terminal_state))));
  82.   if (terminal_table == 0)
  83.     {
  84.       fprintf (stderr, "\nUnable to allocate terminal table.\n");
  85.       fflush (stderr);
  86.       termination_init_error ();
  87.     }
  88. }
  89.  
  90. void
  91. DEFUN_VOID (UX_reset_terminals)
  92. {
  93.   UX_free (terminal_table);
  94.   terminal_table = 0;
  95. }
  96.  
  97. /* This is called from the file-opening code. */
  98. void
  99. DEFUN (terminal_open, (channel), Tchannel channel)
  100. {
  101.   (TERMINAL_BUFFER (channel)) = (-1);
  102.   get_terminal_state (channel, (& (TERMINAL_ORIGINAL_STATE (channel))));
  103. }
  104.  
  105. void
  106. DEFUN (get_terminal_state, (channel, s), Tchannel channel AND Ttty_state * s)
  107. {
  108.   STD_VOID_SYSTEM_CALL
  109.     (syscall_terminal_get_state,
  110.      (UX_terminal_get_state ((CHANNEL_DESCRIPTOR (channel)), s)));
  111. }
  112.  
  113. void
  114. DEFUN (set_terminal_state, (channel, s), Tchannel channel AND Ttty_state * s)
  115. {
  116.   extern int EXFUN (UX_terminal_control_ok, (int fd));
  117.   if (UX_terminal_control_ok (CHANNEL_DESCRIPTOR (channel)))
  118.     STD_VOID_SYSTEM_CALL
  119.       (syscall_terminal_set_state,
  120.        (UX_terminal_set_state ((CHANNEL_DESCRIPTOR (channel)), s)));
  121. }
  122.  
  123. unsigned long
  124. DEFUN (terminal_state_get_ospeed, (s), Ttty_state * s)
  125. {
  126. #ifdef HAVE_TERMIOS
  127.   return (cfgetospeed (TIO (s)));
  128. #else
  129. #ifdef HAVE_TERMIO
  130.   return (((TIO (s)) -> c_cflag) & CBAUD);
  131. #else
  132. #ifdef HAVE_BSD_TTY_DRIVER
  133.   return (s -> sg . sg_ospeed);
  134. #endif /* HAVE_BSD_TTY_DRIVER */
  135. #endif /* not HAVE_TERMIO */
  136. #endif /* not HAVE_TERMIOS */
  137. }
  138.  
  139. unsigned long
  140. DEFUN (terminal_state_get_ispeed, (s), Ttty_state * s)
  141. {
  142. #ifdef HAVE_TERMIOS
  143.   return (cfgetispeed (TIO (s)));
  144. #else
  145. #ifdef HAVE_TERMIO
  146.   return (((TIO (s)) -> c_cflag) & CBAUD);
  147. #else
  148. #ifdef HAVE_BSD_TTY_DRIVER
  149.   return (s -> sg . sg_ispeed);
  150. #endif /* HAVE_BSD_TTY_DRIVER */
  151. #endif /* not HAVE_TERMIO */
  152. #endif /* not HAVE_TERMIOS */
  153. }
  154.  
  155. int
  156. DEFUN (terminal_state_cooked_output_p, (s), Ttty_state * s)
  157. {
  158. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  159.   return ((((TIO (s)) -> c_oflag) & OPOST) != 0);
  160. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  161. #ifdef HAVE_BSD_TTY_DRIVER
  162.   return (((s -> sg . sg_flags) & LLITOUT) == 0);
  163. #endif /* HAVE_BSD_TTY_DRIVER */
  164. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  165. }
  166.  
  167. void
  168. DEFUN (terminal_state_raw_output, (s), Ttty_state * s)
  169. {
  170. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  171.   ((TIO (s)) -> c_oflag) &=~ OPOST;
  172. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  173. #ifdef HAVE_BSD_TTY_DRIVER
  174.   (s -> sg . sg_flags) &=~ ALLDELAY;
  175.   (s -> lmode) |= LLITOUT;
  176. #endif /* HAVE_BSD_TTY_DRIVER */
  177. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  178. }
  179.  
  180. void
  181. DEFUN (terminal_state_cooked_output, (s, channel),
  182.        Ttty_state * s AND Tchannel channel)
  183. {
  184.   Ttty_state * os = (& (TERMINAL_ORIGINAL_STATE (channel)));
  185. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  186.   ((TIO (s)) -> c_oflag) |= (((TIO (os)) -> c_oflag) & OPOST);
  187. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  188. #ifdef HAVE_BSD_TTY_DRIVER
  189.   (s -> sg . sg_flags) =
  190.     (((s -> sg . sg_flags) &~ ALLDELAY) | ((os -> sg . sg_flags) & ALLDELAY));
  191.   (s -> lmode) &=~ ((os -> lmode) & LLITOUT);
  192. #endif /* HAVE_BSD_TTY_DRIVER */
  193. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  194. }
  195.  
  196. int
  197. DEFUN (terminal_state_buffered_p, (s), Ttty_state * s)
  198. {
  199. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  200.   return ((((TIO (s)) -> c_lflag) & ICANON) != 0);
  201. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  202. #ifdef HAVE_BSD_TTY_DRIVER
  203.   return (((s -> sg . sg_flags) & (CBREAK | RAW)) == 0);
  204. #endif /* HAVE_BSD_TTY_DRIVER */
  205. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  206. }
  207.  
  208. void
  209. DEFUN (terminal_state_nonbuffered, (s, fd, polling),
  210.        Ttty_state * s AND
  211.        int fd AND
  212.        int polling)
  213. {
  214. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  215.  
  216.   ((TIO (s)) -> c_lflag) &=~ (ICANON | ECHO);
  217. #ifdef IEXTEN
  218.   ((TIO (s)) -> c_lflag) &=~ IEXTEN;
  219. #endif
  220.   ((TIO (s)) -> c_lflag) |= ISIG;
  221.   ((TIO (s)) -> c_iflag) |= IGNBRK;
  222.   ((TIO (s)) -> c_iflag) &=~ (ICRNL | IXON | ISTRIP);
  223.   ((TIO (s)) -> c_cflag) |= CS8;
  224.   ((TIO (s)) -> c_cflag) &=~ PARENB;
  225.   (((TIO (s)) -> c_cc) [VMIN]) = (polling ? 0 : 1);
  226.   (((TIO (s)) -> c_cc) [VTIME]) = 0;
  227. #ifdef HAVE_TERMIOS
  228.   {
  229.     cc_t disable = (UX_PC_VDISABLE (fd));
  230.     (((TIO (s)) -> c_cc) [VSTOP]) = disable;
  231.     (((TIO (s)) -> c_cc) [VSTART]) = disable;
  232.   }
  233. #endif
  234.  
  235. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  236. #ifdef HAVE_BSD_TTY_DRIVER
  237.  
  238.   (s -> sg . sg_flags) &=~ (ECHO | CRMOD);
  239.   (s -> sg . sg_flags) |= (ANYP | CBREAK);
  240.   (s -> lmode) |= (LPASS8 | LNOFLSH);
  241.   (s -> tc . t_startc) = (-1);
  242.   (s -> tc . t_stopc) = (-1);
  243.   (s -> tc . t_eofc) = (-1);
  244.   (s -> tc . t_brkc) = (-1);
  245. #ifdef HAVE_BSD_JOB_CONTROL
  246.   (s -> ltc . t_rprntc) = (-1);
  247.   (s -> ltc . t_flushc) = (-1);
  248.   (s -> ltc . t_werasc) = (-1);
  249.   (s -> ltc . t_lnextc) = (-1);
  250. #endif /* HAVE_BSD_JOB_CONTROL */
  251.  
  252. #endif /* HAVE_BSD_TTY_DRIVER */
  253. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  254. }
  255.  
  256. void
  257. DEFUN (terminal_state_raw, (s, fd), Ttty_state * s AND int fd)
  258. {
  259.   terminal_state_nonbuffered (s, fd, 0);
  260.  
  261. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  262.  
  263.   ((TIO (s)) -> c_lflag) &=~ ISIG;
  264.  
  265. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  266. #ifdef HAVE_BSD_TTY_DRIVER
  267.  
  268.   (s -> sg . sg_flags) &=~ CBREAK;
  269.   (s -> sg . sg_flags) |= RAW;
  270.   (s -> tc . t_intrc) = (-1);
  271.   (s -> tc . t_quitc) = (-1);
  272. #ifdef HAVE_BSD_JOB_CONTROL
  273.   (s -> ltc . t_suspc) = (-1);
  274.   (s -> ltc . t_dsuspc) = (-1);
  275. #endif /* HAVE_BSD_JOB_CONTROL */
  276.  
  277. #endif /* HAVE_BSD_TTY_DRIVER */
  278. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  279. }
  280.  
  281. void
  282. DEFUN (terminal_state_buffered, (s, channel),
  283.        Ttty_state * s AND
  284.        Tchannel channel)
  285. {
  286.   Ttty_state * os = (& (TERMINAL_ORIGINAL_STATE (channel)));
  287.  
  288. #if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO)
  289.  
  290.   ((TIO (s)) -> c_lflag) |= (ICANON | ISIG);
  291.   ((TIO (s)) -> c_lflag) |= (((TIO (os)) -> c_lflag) & ECHO);
  292. #ifdef IEXTEN
  293.   ((TIO (s)) -> c_lflag) |= (((TIO (os)) -> c_lflag) & IEXTEN);
  294. #endif
  295.   ((TIO (s)) -> c_iflag) = ((TIO (os)) -> c_iflag);
  296.   ((TIO (s)) -> c_cflag) |= CS8;
  297.   ((TIO (s)) -> c_cflag) &=~ PARENB;
  298.   (((TIO (s)) -> c_cc) [VMIN]) = (((TIO (os)) -> c_cc) [VMIN]);
  299.   (((TIO (s)) -> c_cc) [VTIME]) = (((TIO (os)) -> c_cc) [VTIME]);
  300. #ifdef HAVE_TERMIOS
  301.   (((TIO (s)) -> c_cc) [VSTOP]) = (((TIO (os)) -> c_cc) [VSTOP]);
  302.   (((TIO (s)) -> c_cc) [VSTART]) = (((TIO (os)) -> c_cc) [VSTART]);
  303. #endif
  304.  
  305. #else /* not HAVE_TERMIOS nor HAVE_TERMIO */
  306. #ifdef HAVE_BSD_TTY_DRIVER
  307.  
  308.   (s -> sg . sg_flags) &=~ (CBREAK | RAW);
  309.   (s -> sg . sg_flags) |= ANYP;
  310.   (s -> sg . sg_flags) |= ((os -> sg . sg_flags) & (ECHO | CRMOD));
  311.   (s -> lmode) &=~ LNOFLSH;
  312.   (s -> lmode) |= LPASS8;
  313.   (s -> tc . t_intrc) = (os -> tc . t_intrc);
  314.   (s -> tc . t_quitc) = (os -> tc . t_quitc);
  315.   (s -> tc . t_startc) = (os -> tc . t_startc);
  316.   (s -> tc . t_stopc) = (os -> tc . t_stopc);
  317.   (s -> tc . t_eofc) = (os -> tc . t_eofc);
  318.   (s -> tc . t_brkc) = (os -> tc . t_brkc);
  319. #ifdef HAVE_BSD_JOB_CONTROL
  320.   (s -> ltc . t_suspc) = (os -> ltc . t_suspc);
  321.   (s -> ltc . t_dsuspc) = (os -> ltc . t_dsuspc);
  322.   (s -> ltc . t_rprntc) = (os -> ltc . t_rprntc);
  323.   (s -> ltc . t_flushc) = (os -> ltc . t_flushc);
  324.   (s -> ltc . t_werasc) = (os -> ltc . t_werasc);
  325.   (s -> ltc . t_lnextc) = (os -> ltc . t_lnextc);
  326. #endif /* HAVE_BSD_JOB_CONTROL */
  327.  
  328. #endif /* HAVE_BSD_TTY_DRIVER */
  329. #endif /* HAVE_TERMIOS or HAVE_TERMIO */
  330. }
  331.  
  332. unsigned long
  333. DEFUN (OS_terminal_get_ispeed, (channel), Tchannel channel)
  334. {
  335.   Ttty_state s;
  336.   get_terminal_state (channel, (&s));
  337.   return (terminal_state_get_ispeed (&s));
  338. }
  339.  
  340. unsigned long
  341. DEFUN (OS_terminal_get_ospeed, (channel), Tchannel channel)
  342. {
  343.   Ttty_state s;
  344.   get_terminal_state (channel, (&s));
  345.   return (terminal_state_get_ospeed (&s));
  346. }
  347.  
  348. static unsigned int baud_convert [] =
  349. #ifdef _HPUX
  350.   {
  351.     0, 50, 75, 110, 135, 150, 200, 300, 600, 900, 1200,
  352.     1800, 2400, 3600, 4800, 7200, 9600, 19200, 38400
  353.   };
  354. #else
  355.   {
  356.     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
  357.     1800, 2400, 4800, 9600, 19200, 38400
  358.   };
  359. #endif
  360.  
  361. #define BAUD_CONVERT_LENGTH                        \
  362.   ((sizeof (baud_convert)) / (sizeof (baud_convert[0])))
  363.  
  364. unsigned int
  365. DEFUN (arg_baud_index, (argument), unsigned int argument)
  366. {
  367.   return (arg_index_integer (argument, BAUD_CONVERT_LENGTH));
  368. }
  369.  
  370. unsigned int
  371. DEFUN (OS_baud_index_to_rate, (index), unsigned int index)
  372. {
  373.   return (baud_convert [index]);
  374. }
  375.  
  376. int
  377. DEFUN (OS_baud_rate_to_index, (rate), unsigned int rate)
  378. {
  379.   unsigned int * scan = baud_convert;
  380.   unsigned int * end = (scan + BAUD_CONVERT_LENGTH);
  381.   while (scan < end)
  382.     if ((*scan++) = rate)
  383.       return ((scan - 1) - baud_convert);
  384.   return (-1);
  385. }
  386.  
  387. unsigned int
  388. DEFUN_VOID (OS_terminal_state_size)
  389. {
  390.   return (sizeof (Ttty_state));
  391. }
  392.  
  393. void
  394. DEFUN (OS_terminal_get_state, (channel, statep),
  395.        Tchannel channel AND
  396.        PTR statep)
  397. {
  398.   get_terminal_state (channel, statep);
  399. }
  400.  
  401. void
  402. DEFUN (OS_terminal_set_state, (channel, statep),
  403.        Tchannel channel AND
  404.        PTR statep)
  405. {
  406.   set_terminal_state (channel, statep);
  407. }
  408.  
  409. int
  410. DEFUN (OS_terminal_cooked_output_p, (channel), Tchannel channel)
  411. {
  412.   Ttty_state s;
  413.   get_terminal_state (channel, (&s));
  414.   return (terminal_state_cooked_output_p (&s));
  415. }
  416.  
  417. void
  418. DEFUN (OS_terminal_raw_output, (channel), Tchannel channel)
  419. {
  420.   Ttty_state s;
  421.   get_terminal_state (channel, (&s));
  422.   terminal_state_raw_output (&s);
  423.   set_terminal_state (channel, (&s));
  424. }
  425.  
  426. void
  427. DEFUN (OS_terminal_cooked_output, (channel), Tchannel channel)
  428. {
  429.   Ttty_state s;
  430.   get_terminal_state (channel, (&s));
  431.   terminal_state_cooked_output ((&s), channel);
  432.   set_terminal_state (channel, (&s));
  433. }
  434.  
  435. int
  436. DEFUN (OS_terminal_buffered_p, (channel), Tchannel channel)
  437. {
  438.   Ttty_state s;
  439.   get_terminal_state (channel, (&s));
  440.   return (terminal_state_buffered_p (&s));
  441. }
  442.  
  443. void
  444. DEFUN (OS_terminal_buffered, (channel), Tchannel channel)
  445. {
  446.   Ttty_state s;
  447.   get_terminal_state (channel, (&s));
  448.   terminal_state_buffered ((&s), channel);
  449.   set_terminal_state (channel, (&s));
  450. }
  451.  
  452. void
  453. DEFUN (OS_terminal_nonbuffered, (channel), Tchannel channel)
  454. {
  455.   Ttty_state s;
  456.   get_terminal_state (channel, (&s));
  457.   terminal_state_nonbuffered ((&s), (CHANNEL_DESCRIPTOR (channel)), 0);
  458.   set_terminal_state (channel, (&s));
  459. }
  460.  
  461. void
  462. DEFUN (OS_terminal_flush_input, (channel), Tchannel channel)
  463. {
  464.   STD_VOID_SYSTEM_CALL
  465.     (syscall_tcflush, (UX_tcflush ((CHANNEL_DESCRIPTOR (channel)), TCIFLUSH)));
  466. }
  467.  
  468. void
  469. DEFUN (OS_terminal_flush_output, (channel), Tchannel channel)
  470. {
  471.   STD_VOID_SYSTEM_CALL
  472.     (syscall_tcflush, (UX_tcflush ((CHANNEL_DESCRIPTOR (channel)), TCOFLUSH)));
  473. }
  474.  
  475. void
  476. DEFUN (OS_terminal_drain_output, (channel), Tchannel channel)
  477. {
  478.   STD_VOID_SYSTEM_CALL
  479.     (syscall_tcdrain, (UX_tcdrain (CHANNEL_DESCRIPTOR (channel))));
  480. }
  481.  
  482. int
  483. DEFUN_VOID (OS_job_control_p)
  484. {
  485.   return (UX_SC_JOB_CONTROL ());
  486. }
  487.  
  488. #ifdef HAVE_PTYS
  489.  
  490. int
  491. DEFUN_VOID (OS_have_ptys_p)
  492. {
  493.   return (1);
  494. }
  495.  
  496. #ifdef FIRST_PTY_LETTER
  497.  
  498. #define PTY_DECLARATIONS                        \
  499.   int c;                                \
  500.   int i
  501.  
  502. #define PTY_ITERATION                            \
  503.   for (c = FIRST_PTY_LETTER; (c <= 'z'); c += 1)            \
  504.     for (i = 0; (i < 16); i += 1)
  505.  
  506. #define PTY_MASTER_NAME_SPRINTF(master_name)                \
  507.   sprintf ((master_name), "/dev/pty%c%x", c, i)
  508.  
  509. #define PTY_SLAVE_NAME_SPRINTF(slave_name, fd)                \
  510. {                                    \
  511.   sprintf ((slave_name), "/dev/tty%c%x", c, i);                \
  512.   if ((UX_access ((slave_name), (R_OK | W_OK))) < 0)            \
  513.     {                                    \
  514.       UX_close (fd);                            \
  515.       continue;                                \
  516.     }                                    \
  517. }
  518.  
  519. #endif /* FIRST_PTY_LETTER */
  520.  
  521. /* Open an available pty, putting channel in (*ptyv),
  522.    and return the file name of the pty.
  523.    Signal error if none available.  */
  524.  
  525. CONST char *
  526. DEFUN (OS_open_pty_master, (master_fd, master_fname),
  527.        Tchannel * master_fd AND
  528.        CONST char ** master_fname)
  529. {
  530.   static char master_name [24];
  531.   static char slave_name [24];
  532.   int fd;
  533.   PTY_DECLARATIONS;
  534.  
  535. #ifdef PTY_ITERATION
  536.   PTY_ITERATION
  537. #endif
  538.     {
  539.       PTY_MASTER_NAME_SPRINTF (master_name);
  540.     retry_open:
  541.       fd = (UX_open (master_name, O_RDWR, 0));
  542.       if (fd < 0)
  543.     {
  544.       if (errno != EINTR)
  545.         {
  546. #ifdef PTY_ITERATION
  547.           continue;
  548. #else
  549.           error_system_call (errno, syscall_open);
  550. #endif
  551.         }
  552.       deliver_pending_interrupts ();
  553.       goto retry_open;
  554.     }
  555.       PTY_SLAVE_NAME_SPRINTF (slave_name, fd);
  556.       MAKE_CHANNEL (fd, channel_type_pty_master, (*master_fd) =);
  557.       (*master_fname) = master_name;
  558.       return (slave_name);
  559.     }
  560.   error_external_return ();
  561.   return (0);
  562. }
  563.  
  564. void
  565. DEFUN (OS_pty_master_send_signal, (channel, sig), Tchannel channel AND int sig)
  566. {
  567. #ifdef TIOCSIGSEND
  568.   STD_VOID_SYSTEM_CALL
  569.     (syscall_ioctl_TIOCSIGSEND,
  570.      (UX_ioctl ((CHANNEL_DESCRIPTOR (channel)), TIOCSIGSEND, sig)));
  571. #else /* not TIOCSIGSEND */
  572. #ifdef HAVE_BSD_JOB_CONTROL
  573.   int fd = (CHANNEL_DESCRIPTOR (channel));
  574.   int gid;
  575.   STD_VOID_SYSTEM_CALL
  576.     (syscall_ioctl_TIOCGPGRP, (UX_ioctl (fd, TIOCGPGRP, (&gid))));
  577.   STD_VOID_SYSTEM_CALL (syscall_kill, (UX_kill ((-gid), sig)));
  578. #else /* not HAVE_BSD_JOB_CONTROL */
  579.   error_unimplemented_primitive ();
  580. #endif /* HAVE_BSD_JOB_CONTROL */
  581. #endif /* TIOCSIGSEND */
  582. }
  583.  
  584. #else /* not HAVE_PTYS */
  585.  
  586. int
  587. DEFUN_VOID (OS_have_ptys_p)
  588. {
  589.   return (0);
  590. }
  591.  
  592. CONST char *
  593. DEFUN (OS_open_pty_master, (master_fd, master_fname),
  594.        Tchannel * master_fd AND
  595.        CONST char ** master_fname)
  596. {
  597.   error_unimplemented_primitive ();
  598. }
  599.  
  600. void
  601. DEFUN (OS_pty_master_send_signal, (channel, sig), Tchannel channel AND int sig)
  602. {
  603.   error_unimplemented_primitive ();
  604. }
  605.  
  606. #endif /* not HAVE_PTYS */
  607.  
  608. void
  609. DEFUN (OS_pty_master_kill, (channel), Tchannel channel)
  610. {
  611.   OS_pty_master_send_signal (channel, SIGKILL);
  612. }
  613.  
  614. void
  615. DEFUN (OS_pty_master_stop, (channel), Tchannel channel)
  616. {
  617.   OS_pty_master_send_signal (channel, SIGTSTP);
  618. }
  619.  
  620. void
  621. DEFUN (OS_pty_master_continue, (channel), Tchannel channel)
  622. {
  623.   OS_pty_master_send_signal (channel, SIGCONT);
  624. }
  625.  
  626. void
  627. DEFUN (OS_pty_master_interrupt, (channel), Tchannel channel)
  628. {
  629.   OS_pty_master_send_signal (channel, SIGINT);
  630. }
  631.  
  632. void
  633. DEFUN (OS_pty_master_quit, (channel), Tchannel channel)
  634. {
  635.   OS_pty_master_send_signal (channel, SIGQUIT);
  636. }
  637.  
  638. void
  639. DEFUN (OS_pty_master_hangup, (channel), Tchannel channel)
  640. {
  641.   OS_pty_master_send_signal (channel, SIGHUP);
  642. }
  643.